In [1]:
pkg_ver = lambda pkg: "{:<20}{:}".format(pkg.__name__,pkg.__version__)

# ROOT
import uproot
print(pkg_ver(uproot))
import ROOT

# Machine Learning
import sklearn
print(pkg_ver(sklearn))
import torch
print(pkg_ver(torch))

# Data science
import scipy
print(pkg_ver(scipy))
import numpy
print(pkg_ver(numpy))
import pandas
print(pkg_ver(pandas))
import awkward
print(pkg_ver(awkward))

# Visualizations
import matplotlib
print(pkg_ver(matplotlib))
import matplotlib.pyplot as plt
import hvplot
print(pkg_ver(hvplot))
import hvplot.pandas
pandas.options.plotting.backend = 'holoviews'

import tqdm
print(pkg_ver(tqdm))
from tqdm.auto import tqdm
tqdm.pandas()

import glob
import re
import hashlib
uproot              5.0.7
Welcome to JupyROOT 6.28/02
sklearn             1.2.2
torch               2.0.0
scipy               1.10.1
numpy               1.23.5
pandas              1.5.3
awkward             2.2.0
matplotlib          3.7.1
hvplot              None
tqdm                4.62.3
In [2]:
%jsroot
In [3]:
class spectrum:
    
    def __init__(self, File_, Configuration_, Window_, Time_):  

        self.__FileName = File_
        self.__Configuration = Configuration_
        self.__Window = Window_
        self.__Time = Time_
        self.__File = uproot.open(File_)
        self.__DF = self.DF()
        self.__TH1D = self.TH1D()
        
    def __call__(self, ch):
        return numpy.polyval(self.__Calibration[::-1],ch)

    def File(self):
        return self.__File
    
    def FileName(self):
        return self.__FileName
    
    def DF(self):
        # Gets ak dataframe
        df_ak = self.__File['SCATTERER_A;1'].arrays(["TimeStamp", "Total_Deposited_Energy", "Pixel_multiplicity"],library="ak")
        #Transform from ak to pandas
        df = awkward.to_dataframe(df_ak)
        # Apply energy calibration to individual entries
        #df["Total_Deposited_Energy"] = df.Total_Deposited_Energy.progress_map(lambda x: numpy.polyval(
        #    calibrations_df.query("crystal == 'A0' & cw == '100'").iloc[0][[0,1,2]][::-1],x
        #))
        # Temperature df
        df_temp = self.__File['T_ASIC_0;1'].values()
        # Temperature change indexes
        temp_ch = numpy.concatenate((
            [df.TimeStamp.min()-1],
            numpy.mean(
                numpy.array(
                    [
                        df_temp[0][numpy.where(df_temp[1][:-1] != df_temp[1][1:])[0]],   # Gives the last value before change
                        df_temp[0][numpy.where(df_temp[1][:-1] != df_temp[1][1:])[0]+1], # Gives the first value after change
                    ]
                ),
                axis=0
            ),
            [df.TimeStamp.max()+1]
        ))
        # Add temperature information
        df["Temperature"] = df.TimeStamp.map(lambda x:
            numpy.concatenate((
                df_temp[1][numpy.where(df_temp[1][:-1] != df_temp[1][1:])[0]],
                [df_temp[1][-1]]
            ))[numpy.searchsorted(temp_ch, x)-1] 
        )
                        
        return df
    
    def TH1D(self):
        # Create histogram
        hist_dict = {i: ROOT.TH1F("",f"Events for {i}ºC;Energy [keV];Counts",2000,0,2000) for i in self.__DF.Temperature.unique()}
        # Add entries
        for i in self.__DF.iterrows():
            hist_dict[i[1].Temperature].Fill(i[1].Total_Deposited_Energy)
        # Scale
        for i in hist_dict:
            hist_dict[i].Scale(1/len(self.__DF.query("Temperature == @i").index))
        
        return hist_dict
    
    def get_TH1D(self):        
        return self.__TH1D
    
    def Configuration(self):
        return self.__Configuration
    
    def Window(self):
        return self.__Window
In [4]:
calp = glob.glob('/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/Calibration/**/*.CALp', recursive=True)

calibrations = []

for i in calp:
    line = pandas.read_csv(
        i,
        sep = "      :  ",
        skiprows=[0,4,5,6],
        header=None,
        engine="python"
    ).drop([0], axis=1).T
    
    line["crystal"] = i.split("/")[-1][:2]
    line["cw"] = i.split("/")[-1][5:8]
    
    calibrations.append(line)
    
calibrations_df = pandas.concat(calibrations)
In [35]:
def get_resolution(spectr,temp,en):
    
    TH1D = spectr.get_TH1D()[temp]
    
    #TH1D.GetXaxis().SetRange(TH1D.FindBin(en-250),TH1D.FindBin(en+600))
    TH1D.GetXaxis().SetRange(TH1D.FindBin(en-100),TH1D.FindBin(en+250))
    
    MaxBin   = TH1D.FindBin(TH1D.GetMaximumBin())
    
    ADC_Low  = MaxBin-100
    ADC_High = MaxBin+100

    gaussFit = ROOT.TF1("gaussFit", "gaus(0)+pol3(3)", ADC_Low, ADC_High)
    gaussFit.SetParameters(TH1D.GetMaximum(),MaxBin,7,0,0,0,0)
    TH1D.Fit(gaussFit,"QR")
    
    sigma = abs(gaussFit.GetParameter(2))
    centroid_ch = gaussFit.GetParameter(1)
    
    cal = lambda x: numpy.polyval(calibrations_df.query("crystal == 'A0' & cw == '100'").iloc[0][[0,1,2]][::-1],x)
    x1 = cal(centroid_ch+sigma*numpy.sqrt(2*numpy.log(2)))
    x2 = cal(centroid_ch-sigma*numpy.sqrt(2*numpy.log(2)))
    centroid = cal(centroid_ch)
        
    fwhm = x1-x2
            
    return sigma*numpy.sqrt(2*numpy.log(2))*2/centroid_ch*100, (fwhm/centroid)*100, centroid, (centroid_ch-en)/en*100, centroid_ch
In [16]:
def TH1D_draw(spectr,temp,en):
    
    canvas = ROOT.TCanvas()
    canvas.cd()
    
    TH1D = spectr.get_TH1D()[temp]
    
    #TH1D.SetTitle(repr(cell))
    TH1D.SetStats(False)
    
    latex = ROOT.TLatex()
    latex.SetNDC()
    latex.SetTextSize(0.03)
    
    TH1D.Draw("PE PLC")
    
    l1,l2,l3,l4,l5 = get_resolution(spectr,temp,en)
        
    latex.DrawText(0.7, 0.8, "R(ch): {:.2f}%".format(l1))
    latex.DrawText(0.7, 0.7, "R(en): {:.2f}%".format(l2))
    latex.DrawText(0.7, 0.6, "E: {:.0f}keV".format( l3))
    latex.DrawText(0.7, 0.5, "#Delta E: {:.2f}%".format(l4))
            
    return canvas
In [17]:
Data = {
    100: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_19/Temperature_Cs137_center_fans_D.2023_05_19_T.15_50_00_C.itedABCD_lab_custom_2023.02.22_4.0v_887_45s_serie1_20_CW{win}.root",
    200: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_26/Temperature_Cs137_center_D.2023_05_26_T.12_30_56_C.itedABCD_lab_custom_2023.02.22_4.0v_887_300s_CW{win}.root",
    300: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_26/Temperature_Cs137_center_D.2023_05_26_T.12_08_34_C.itedABCD_lab_custom_2023.02.22_4.0v_887_600s_CW{win}.root",
    400: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_29/Temperature_Na22_D.2023_05_29_T.11_57_12_C.itedABCD_lab_custom_2023.02.22_4.0v_887_900s_CW{win}.root",
    500: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_29/Temperature_Cs137_D.2023_05_29_T.12_35_13_C.itedABCD_lab_custom_2023.02.22_4.0v_887_900s_CW{win}.root",
    1:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_53_56_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie1_40_CW{win}.root",
    2:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_54_14_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie2_40_CW{win}.root",
    3:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_54_33_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie3_40_CW{win}.root",
    4:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_54_51_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie4_40_CW{win}.root",
    5:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_55_10_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie5_40_CW{win}.root",
    6:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_55_29_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie6_40_CW{win}.root",
    7:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_55_47_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie7_40_CW{win}.root",
    8:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_56_06_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie8_40_CW{win}.root",
    9:  lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_56_24_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie9_40_CW{win}.root",
    10: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_56_43_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie10_40_CW{win}.root",
    11: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_57_02_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie11_40_CW{win}.root",
    12: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_57_20_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie12_40_CW{win}.root",
    13: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_57_39_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie13_40_CW{win}.root",
    14: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_57_57_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie14_40_CW{win}.root",
    15: lambda win: f"/run/media/bgameiro/d043b5e4-57a4-457e-8839-cb1adc9c72bc/Data/data_2023_05_22/Temperature_Cs137_center_D.2023_05_22_T.15_58_16_C.itedABCD_lab_custom_2023.02.22_4.0v_887_15s_serie15_40_CW{win}.root",
}
In [64]:
en=511
cal = calibrations_df.query("crystal == 'A0' & cw == '100'").iloc[0][[0,1,2]][::-1]
p = numpy.poly1d(cal)
en = list(set(i for i in (p - en).roots if i > 0))[0]
en
Out[64]:
206.419806623866
In [18]:
entries = []

for i in tqdm(Data):
    for CW in tqdm([100,200]):
        
        file = Data[i](CW)
        
        spectr = spectrum(
                file,
                1,
                CW,
                int(re.search("_(\d{2,4})s_", file).group(1))
        )
        
        open_file = uproot.open(file)
        
        en = 661.7 if "Cs137" in file else 511
        
        cal = calibrations_df.query("crystal == 'A0' & cw == '100'").iloc[0][[0,1,2]][::-1]
        p = numpy.poly1d(cal)
        en = list(set(i for i in (p - en).roots if i > 0))[0]
        
        for temp in tqdm(pandas.Series(open_file['T_ASIC_0;1'].values()[1]).unique()):


            res_ch, res_en, cent, fit, cent_ch = get_resolution(spectr,temp,en)

            entries.append(
                pandas.DataFrame({
                    "resolution": res_en,
                    "fit": fit,
                    "cw": CW,
                    "obj": spectr,
                    "peak_en": cent,
                    "peak_ch": cent_ch,
                    "temperature": temp,
                    "measurement": hashlib.sha1(file[:-10].encode("UTF-8")).hexdigest()[:5],
                    "energy": en,
                }, index=[0])
            )
                    
entries_df = pandas.concat(entries, ignore_index=True)
  0%|          | 0/20 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/9 [00:00<?, ?it/s]
  0%|          | 0/9 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/25 [00:00<?, ?it/s]
  0%|          | 0/25 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/26 [00:00<?, ?it/s]
  0%|          | 0/26 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/34 [00:00<?, ?it/s]
  0%|          | 0/34 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/3 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/1 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
  0%|          | 0/2 [00:00<?, ?it/s]
In [77]:
entries_df
Out[77]:
resolution fit cw obj peak_en peak_ch temperature measurement deviation_ch energy
0 6.104301 29.415677 100 <__main__.spectrum object at 0x7f4ba4888820> 856.343535 363.885632 24.6 6e1cf 31.794869 661.7
1 6.179620 28.173558 100 <__main__.spectrum object at 0x7f4ba4888820> 848.124430 360.226862 24.8 6e1cf 30.469707 661.7
2 6.152740 27.843299 100 <__main__.spectrum object at 0x7f4ba4888820> 845.939111 359.253362 25.1 6e1cf 30.117118 661.7
3 6.160810 26.310295 100 <__main__.spectrum object at 0x7f4ba4888820> 835.795222 354.730702 25.2 6e1cf 28.479066 661.7
4 6.307583 25.595279 100 <__main__.spectrum object at 0x7f4ba4888820> 831.063964 352.619104 25.5 6e1cf 27.714272 661.7
... ... ... ... ... ... ... ... ... ... ...
241 6.140938 -4.710555 200 <__main__.spectrum object at 0x7f49510bd120> 630.657791 261.873507 31.4 a7382 -5.152660 661.7
242 6.532014 -5.024121 100 <__main__.spectrum object at 0x7f4ba41f3d00> 628.593332 260.925062 31.3 030fd -5.496175 661.7
243 6.506611 -5.217419 100 <__main__.spectrum object at 0x7f4ba41f3d00> 627.220079 260.294008 31.4 030fd -5.724734 661.7
244 6.281325 -4.620199 200 <__main__.spectrum object at 0x7f4ba4279ed0> 631.207892 262.126183 31.3 030fd -5.061143 661.7
245 6.291890 -4.956720 200 <__main__.spectrum object at 0x7f4ba4279ed0> 628.953232 261.090426 31.4 030fd -5.436282 661.7

246 rows × 10 columns

In [78]:
entries_df.to_pickle('entries_df_all.pickle.gzip',compression='gzip')
In [79]:
entries_df.hvplot.scatter("temperature","peak_ch",by=["energy","cw"],hover_cols=["measurement"])
Out[79]:
In [80]:
entries_df.hvplot.scatter("temperature","peak_en",by=["energy","cw"],hover_cols=["measurement"])
Out[80]:
In [81]:
entries_df.hvplot.scatter("temperature","deviation_ch",by=["energy","cw"],hover_cols=["measurement"])
Out[81]:
In [82]:
entries_df.hvplot.scatter("temperature","fit",by=["energy","cw"],hover_cols=["measurement"])
Out[82]:
In [83]:
entries_df.hvplot.scatter("temperature","resolution",by=["energy","cw"],hover_cols=["measurement"])
Out[83]:
In [55]:
entries_df.query("temperature == 30.4")
Out[55]:
resolution fit cw obj peak_en peak_ch temperature measurement test energy
211 6.413937 140.536152 100 <__main__.spectrum object at 0x7f4ba4589ba0> 664.121357 277.207468 30.4 a15b3 13.987299 661.7
213 6.073674 141.229504 200 <__main__.spectrum object at 0x7f4b4fdb9ba0> 666.035704 278.082425 30.4 a15b3 12.220411 661.7
214 6.495296 139.062356 100 <__main__.spectrum object at 0x7f4ba478f730> 660.052199 275.346843 30.4 b038e 27.037095 661.7
216 6.315008 139.652253 200 <__main__.spectrum object at 0x7f4b78482b00> 661.680908 276.091703 30.4 b038e 25.857501 661.7
In [1]:
#TH1D_draw(entries_df.iloc[211].obj,30.4,275).Draw()
In [ ]: